package com.elitel.frame.web.serverinfo.service.impl;

import com.elitel.common.utils.SpringUtils;
import com.elitel.common.utils.SysUserUtils;
import com.elitel.frame.web.acservicefilterfield.dao.AcServiceFilterFieldsDao;
import com.elitel.frame.web.acservicefilterfield.entity.AcServiceFilterFields;
import com.elitel.frame.web.cfgqueryfield.dao.CfgQueryFieldDao;
import com.elitel.frame.web.cfgqueryfield.entity.CfgQueryField;
import com.elitel.frame.web.cfgservergroup.entity.CfgServerGroupRel;
import com.elitel.frame.web.cfgservergroup.service.CfgServerGroupRelService;
import com.elitel.frame.web.cfgserverinfo.dao.CfgServerInfoDao;
import com.elitel.frame.web.cfgserverinfo.entity.CfgServerInfo;
import com.elitel.frame.web.cfgserverinfo.service.CfgServerInfoService;
import com.elitel.frame.web.cfgshowfield.dao.CfgShowFieldDao;
import com.elitel.frame.web.cfgshowfield.entity.CfgShowField;
import com.elitel.frame.web.common.asserts.CommonAssert;
import com.elitel.frame.web.common.idworker.IdWorker;
import com.elitel.frame.web.serverinfo.dto.ServerConfigDTO;
import com.elitel.frame.web.serverinfo.dto.ServerInfoDTO;
import com.elitel.frame.web.serverinfo.dto.ServerQueryFieldDTO;
import com.elitel.frame.web.serverinfo.dto.ServerShowFieldDTO;
import com.elitel.frame.web.serverinfo.service.ServerInfoService;
import com.elitel.frame.web.serverinfocustom.service.SererInfoCustomService;
import com.elitel.frame.web.serverinfocustom.service.impl.SimServerInfoService;
import com.elitel.frame.web.serverinfocustom.service.impl.SingleServerInfoService;
import com.elitel.frame.web.serverinfocustom.service.impl.SqlServerInfoService;
import com.elitel.frame.web.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.elitel.frame.web.serverinfo.constants.ServerConstant.*;

/**
 * @author m
 */
@Service
public class ServerInfoServiceImpl implements ServerInfoService {

    private Map<String, SererInfoCustomService> beanMap;
    private Map<String, Integer> serverTypeMap;

    @Resource
    private CfgServerInfoService cfgServerInfoService;
    @Resource
    private CfgServerGroupRelService groupRelService;
    @Resource
    private CfgQueryFieldDao cfgQueryFieldDao;
    @Resource
    private CfgShowFieldDao cfgShowFieldDao;
    @Resource
    private AcServiceFilterFieldsDao acServiceFilterFieldsDao;
    @Resource
    private CfgServerInfoDao cfgServerInfoDao;

    @PostConstruct
    public void init() {
        beanMap = new HashMap<>();
        // 将实现类注册到容器
        beanMap.put(SINGLE_SERVER, SpringUtils.getBean(SingleServerInfoService.class));
        beanMap.put(SQL_SERVER, SpringUtils.getBean(SqlServerInfoService.class));
        beanMap.put(SIM_SERVER, SpringUtils.getBean(SimServerInfoService.class));

        serverTypeMap = new HashMap<>();
        serverTypeMap.put(SINGLE_SERVER, 1);
        serverTypeMap.put(SQL_SERVER, 4);
        serverTypeMap.put(SIM_SERVER, 10);
    }

    @Override
    public String updateCacheStatus(String serverId, String cacheFlag) {
        if (serverId != null&& cacheFlag != null) {
            CfgServerInfo info = new CfgServerInfo();
            info.setGuid(serverId);
            info.setCacheDur("1".equals(cacheFlag) ? 60 : 0);
            int update = cfgServerInfoDao.update(info);
            return update == 1 ? "ok" : "update failed";
        }
        return "serverId cacheFlag 不能为空";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveData(ServerInfoDTO dto) throws Exception {
        // 校验并填充参数
        this.checkAndFillDto(dto);
        // 保存服务基本信息
        String serverId = this.saveBasicConfig(dto.getBasicConfig());
        // 保存查询参数信息
        this.saveQueryFieldList(dto);
        // 保存显示字段信息
        this.saveShowFieldList(dto);
        // 保存过滤字段信息
        this.saveFilterFieldList(dto);
        // 保存自定义信息
        SererInfoCustomService sererInfoCustomService = beanMap.get(dto.getBasicConfig().getServerType());
        if (sererInfoCustomService == null) {
            throw new RuntimeException("未找到对应的服务类型");
        }
        sererInfoCustomService.save(dto);
        return serverId;
    }

    private void checkAndFillDto(ServerInfoDTO dto) {
        ServerConfigDTO basicConfig = dto.getBasicConfig();
        if (basicConfig != null) {
            CommonAssert.notBlank(basicConfig.getServerType(), "服务类型不能为空");
            CommonAssert.notBlank(basicConfig.getGroupId(), "服务分组不能为空");
            CommonAssert.notBlank(basicConfig.getServerName(), "服务名称不能为空");
            String apiPath = basicConfig.getApiPath();
            CommonAssert.notBlank(apiPath, "api path 不能为空");
            // 判断apiPath是否以/开头
            if (!apiPath.startsWith("/")) {
                apiPath = "/" + apiPath;
            }
            // 校验apiPath格式
            if (!isValidPath(apiPath)) {
                throw new RuntimeException("api path 格式错误");
            }
            // 校验不能重复
            CfgServerInfo apiPathExist = this.cfgServerInfoDao.queryApiPathExist(basicConfig.getServerId(), apiPath);
            if (apiPathExist != null) {
                throw new RuntimeException("api path 已存在");
            }

            basicConfig.setApiPath(apiPath);
            if (StringUtils.isEmpty(basicConfig.getCacheFlag())) {
                basicConfig.setCacheFlag("0");
            }
            if (StringUtils.isEmpty(basicConfig.getTransJsonFlag())) {
                basicConfig.setTransJsonFlag("0");
            }
            if (StringUtils.isEmpty(basicConfig.getPaginationFlag())) {
                basicConfig.setPaginationFlag("1");
            }
        } else {
            throw new RuntimeException("服务信息不能为空");
        }
        List<ServerQueryFieldDTO> queryFieldList = dto.getQueryFieldList();
        if (!CollectionUtils.isEmpty(queryFieldList)) {
            for (ServerQueryFieldDTO queryField : queryFieldList) {
                if (StringUtils.isEmpty(queryField.getFieldCode())) {
                    queryField.setFieldCode(queryField.getMetaFieldCode());
                }
                if (StringUtils.isEmpty(queryField.getFieldName())) {
                    queryField.setFieldName(queryField.getFieldCode());
                }
                if (StringUtils.isEmpty(queryField.getFieldCondition())) {
                    queryField.setFieldCondition("=");
                }
                if (queryField.getFieldSearchType() == null) {
                    queryField.setFieldSearchType(1);
                }
                if (queryField.getFieldSearchType() == 2 && queryField.getFieldDefaultValue() == null) {
                    throw new RuntimeException("字段查询类型为固定参数时, 默认值不能为空");
                }
                if (StringUtils.isEmpty(queryField.getFieldType())) {
                    queryField.setFieldType("String");
                }
                if (StringUtils.isEmpty(queryField.getRequiredFlag())) {
                    queryField.setRequiredFlag("0");
                }
            }
        }
        List<ServerShowFieldDTO> showFieldList = dto.getShowFieldList();
        if (!CollectionUtils.isEmpty(showFieldList)) {
            for (ServerShowFieldDTO showField : showFieldList) {
                if (StringUtils.isEmpty(showField.getFieldCode())) {
                    showField.setFieldCode(showField.getMetaFieldCode());
                }
                if (StringUtils.isEmpty(showField.getFieldName())) {
                    showField.setFieldName(showField.getFieldCode());
                }
                if (StringUtils.isEmpty(showField.getFieldType())) {
                    showField.setFieldType("String");
                }
            }
        }

    }

    // 校验路径是否合法：不能包含中文、空格和特殊符号
    public static boolean isValidPath(String path) {
        if (path == null || path.isEmpty()) return false;

        // 正则说明：
        // ^[a-zA-Z0-9/_\-\.]+$ ：只能包含字母、数字、下划线、斜杠、连字符、点号
        // 不包含空格、中文、其他特殊字符
        String pattern = "^[a-zA-Z0-9/_\\-\\.]+$";
        return path.matches(pattern);
    }

    private String saveBasicConfig(ServerConfigDTO basicConfig) {

        // 转换为CfgServerInfo
        CfgServerInfo cfgServerInfo = getCfgServerInfo(basicConfig);

        // 保存服务基本信息
        String serverId = cfgServerInfo.getGuid();
        CfgServerInfo dbData = this.cfgServerInfoDao.queryById(serverId);
        if (dbData == null) {
            // 新增的话serverId重新赋值
            serverId = IdWorker.createStrId();
            cfgServerInfo.setGuid(serverId);
            // 此处一定要保证服务编码与guid一致
            cfgServerInfo.setServicecode(serverId);
            basicConfig.setServiceCode(serverId);
            cfgServerInfo.setCreatedate(LocalDateTime.now());
            cfgServerInfo.setCreateuser(SysUserUtils.getLoginAccount());
            this.cfgServerInfoDao.insert(cfgServerInfo);
        } else {
            basicConfig.setServiceCode(dbData.getServicecode());
            this.cfgServerInfoDao.update(cfgServerInfo);
        }

        // 重要 设置serverId
        basicConfig.setServerId(serverId);

        // 保存服务分组信息
        String groupId = basicConfig.getGroupId();
        groupRelService.deleteByServerId(serverId);
        CfgServerGroupRel rel = new CfgServerGroupRel();
        rel.setId(IdWorker.createStrId());
        rel.setGroupId(groupId);
        rel.setServerId(serverId);
        rel.setCreatedTime(new Date());
        rel.setCreatedUser(SysUserUtils.getLoginAccount());
        groupRelService.insert(rel);

        return serverId;
    }


    private void saveQueryFieldList(ServerInfoDTO dto) {
        // 先删除,后保存
        String serverId = getServerIdOrCode(dto.getBasicConfig());
        cfgQueryFieldDao.deleteByServerId(serverId);
        // 获取CfgQueryField集合
        List<CfgQueryField> cfgQueryFieldList = getCfgQueryFieldList(dto);
        if (!CollectionUtils.isEmpty(cfgQueryFieldList)) {
            cfgQueryFieldDao.insertBatch(cfgQueryFieldList);
        }
    }


    private void saveShowFieldList(ServerInfoDTO dto) {
        String serverId = getServerIdOrCode(dto.getBasicConfig());
        // 先删除,后保存
        cfgShowFieldDao.deleteByServerId(serverId);
        List<CfgShowField> cfgShowFieldList = getCfgShowFieldList(dto);
        if (!CollectionUtils.isEmpty(cfgShowFieldList)) {
            cfgShowFieldDao.insertBatch(cfgShowFieldList);
        }
    }


    private void saveFilterFieldList(ServerInfoDTO dto) {
        List<AcServiceFilterFields> filterFields = dto.getFilterFields();
        // 先删除, 后保存
        acServiceFilterFieldsDao.deleteByServerId(dto.getBasicConfig().getServerId());
        if (!CollectionUtils.isEmpty(filterFields)) {
            for (AcServiceFilterFields item : filterFields) {
                item.setCreatedTime(new Date());
                item.setCreatedUser(SysUserUtils.getLoginAccount());
                item.setUpdatedTime(new Date());
                item.setUpdatedUser(SysUserUtils.getLoginAccount());
                item.setServiceId(dto.getBasicConfig().getServerId());
                item.setFilterFieldId(IdWorker.createStrId());
            }
            acServiceFilterFieldsDao.insertBatch(filterFields);
        }

    }


    public static CfgServerInfo getCfgServerInfo(ServerConfigDTO basicConfig) {
        CfgServerInfo cfgServerInfo = new CfgServerInfo();
        cfgServerInfo.setGuid(basicConfig.getServerId());
        cfgServerInfo.setPcode(basicConfig.getPcode());
        cfgServerInfo.setServicetype(basicConfig.getServerType());
        cfgServerInfo.setRemark(basicConfig.getRemark());
        cfgServerInfo.setStatus(1);
        cfgServerInfo.setServicename(basicConfig.getServerName());
        cfgServerInfo.setPaginationFlag("1".equals(basicConfig.getPaginationFlag()) ? 1 : 0);
        cfgServerInfo.setSysDataLabelId(basicConfig.getSysDataLabelId());
        cfgServerInfo.setCacheDur("1".equals(basicConfig.getCacheFlag()) ? 60 : 0);
        cfgServerInfo.setApiPath(basicConfig.getApiPath());
        cfgServerInfo.setResCvsJs(basicConfig.getResCvsJs());
        cfgServerInfo.setTableCodes(basicConfig.getTableCodes());
        cfgServerInfo.setTransJsonFlag(basicConfig.getTransJsonFlag());
        cfgServerInfo.setDbKey(basicConfig.getDbKey());
        return cfgServerInfo;
    }

    private List<CfgQueryField> getCfgQueryFieldList(ServerInfoDTO dto) {
        ServerConfigDTO basicConfig = dto.getBasicConfig();
        List<ServerQueryFieldDTO> queryFieldList = dto.getQueryFieldList();
        ArrayList<CfgQueryField> resList = new ArrayList<>();
        if (queryFieldList != null && !queryFieldList.isEmpty()) {
            for (ServerQueryFieldDTO queryField : queryFieldList) {
                CfgQueryField cfgQueryField = new CfgQueryField();
                cfgQueryField.setGuid(IdWorker.createStrId());
                cfgQueryField.setServiceid(getServerIdOrCode(basicConfig));
                cfgQueryField.setServicetype(serverTypeMap.get(basicConfig.getServerType()));
                cfgQueryField.setQueryorder(queryField.getFieldOrder());
                cfgQueryField.setShowtype(0);
                cfgQueryField.setRemark(queryField.getRemark());
                cfgQueryField.setCreatedate(LocalDateTime.now());
                cfgQueryField.setCreateuser(SysUserUtils.getLoginAccount());
                cfgQueryField.setEnumvalue("");
                cfgQueryField.setFieldaddonsguid(queryField.getMetaFieldId());
                cfgQueryField.setParametercode(queryField.getFieldCode());
                cfgQueryField.setParametercondition(queryField.getFieldCondition());
                cfgQueryField.setGrade("");
                cfgQueryField.setParametertype(queryField.getFieldSearchType());
                cfgQueryField.setParametervalue(queryField.getFieldDefaultValue());
                cfgQueryField.setParamformat(queryField.getFieldType());
                cfgQueryField.setRequiredFlag(queryField.getRequiredFlag());
                cfgQueryField.setParametername(queryField.getFieldName());
                cfgQueryField.setExt1(queryField.getExt1());
                cfgQueryField.setMetaFieldCode(queryField.getMetaFieldCode());
                resList.add(cfgQueryField);
            }
        }
        return resList;
    }


    private List<CfgShowField> getCfgShowFieldList(ServerInfoDTO dto) {
        ServerConfigDTO basicConfig = dto.getBasicConfig();
        ArrayList<CfgShowField> resList = new ArrayList<>();
        List<ServerShowFieldDTO> showFieldList = dto.getShowFieldList();
        if (showFieldList != null && !showFieldList.isEmpty()) {
            for (ServerShowFieldDTO showField : showFieldList) {
                CfgShowField cfgShowField = new CfgShowField();
                cfgShowField.setGuid(IdWorker.createStrId());
                cfgShowField.setServiceid(getServerIdOrCode(basicConfig));
                cfgShowField.setServicetype(serverTypeMap.get(basicConfig.getServerType()));
                cfgShowField.setMasterdetailid("");
                cfgShowField.setFieldaddonsguid(showField.getMetaFieldId());
                cfgShowField.setShoworder(showField.getFieldOrder());
                cfgShowField.setRemark(showField.getRemark());
                cfgShowField.setCreatedate(LocalDateTime.now());
                cfgShowField.setCreateuser(SysUserUtils.getLoginAccount());
                cfgShowField.setCustomalias(showField.getFieldCode());
                cfgShowField.setCustomfieldnamealias(showField.getFieldName());
                // 元数据字段编码 名称 类型
                cfgShowField.setFieldcode(showField.getMetaFieldCode());
                cfgShowField.setFieldtype(showField.getFieldType());
                cfgShowField.setFieldname(showField.getFieldName());
                resList.add(cfgShowField);
            }
        }
        return resList;
    }


    @Override
    public ServerInfoDTO selectByServerId(String serverId) {
        ServerInfoDTO res = new ServerInfoDTO();
        // 查询基本配置信息
        ServerConfigDTO basicConfig = this.selectBasicConfig(serverId);
        // 兼容老逻辑
        String serverIdOrCode = getServerIdOrCode(basicConfig);
        // 查询字段列表
        List<ServerQueryFieldDTO> queryFieldList = this.selectQueryFieldList(serverIdOrCode);
        // 显示字段列表
        List<ServerShowFieldDTO> showFieldList = this.selectShowFieldList(serverIdOrCode);
        // 过滤字段列表
        List<AcServiceFilterFields> filterFields = this.selectFilterFieldList(serverId);
        // 查询自定义信息
        Map<String, Object> customInfo = beanMap.get(basicConfig.getServerType()).selectByServerId(serverIdOrCode);
        res.setBasicConfig(basicConfig);
        res.setQueryFieldList(queryFieldList);
        res.setShowFieldList(showFieldList);
        res.setFilterFields(filterFields);
        res.setCustomInfo(customInfo);
        return res;
    }


    private ServerConfigDTO selectBasicConfig(String serverId) {
        ServerConfigDTO configDTO = new ServerConfigDTO();
        CfgServerInfo cfgServerInfo = cfgServerInfoService.queryById(serverId);
        configDTO.setServerId(cfgServerInfo.getGuid());
        CfgServerGroupRel rel = new CfgServerGroupRel();
        rel.setServerId(serverId);
        List<CfgServerGroupRel> cfgServerGroupRels = groupRelService.queryList(rel);
        if (!CollectionUtils.isEmpty(cfgServerGroupRels)) {
            configDTO.setGroupId(cfgServerGroupRels.stream().map(CfgServerGroupRel::getGroupId).collect(Collectors.joining(",")));
        }
        configDTO.setSysDataLabelId(cfgServerInfo.getSysDataLabelId());
        configDTO.setServerName(cfgServerInfo.getServicename());
        configDTO.setApiPath(cfgServerInfo.getApiPath());
        configDTO.setCacheFlag((cfgServerInfo.getCacheDur() == null || cfgServerInfo.getCacheDur() == 0) ? "0" : "1");
        configDTO.setResCvsJs(cfgServerInfo.getResCvsJs());
        configDTO.setTransJsonFlag(cfgServerInfo.getTransJsonFlag());
        configDTO.setRemark(cfgServerInfo.getRemark());
        Integer paginationFlag = cfgServerInfo.getPaginationFlag();
        configDTO.setPaginationFlag((paginationFlag == null || paginationFlag == 1) ? "1" : "0");
        configDTO.setTableCodes(cfgServerInfo.getTableCodes());
        configDTO.setDbKey(cfgServerInfo.getDbKey());
        configDTO.setPcode(cfgServerInfo.getPcode());
        configDTO.setServerType(cfgServerInfo.getServicetype());
        configDTO.setServiceCode(cfgServerInfo.getServicecode());
        return configDTO;
    }

    private List<ServerQueryFieldDTO> selectQueryFieldList(String serverId) {
        CfgQueryField where = new CfgQueryField();
        where.setServiceid(serverId);
        List<CfgQueryField> cfgQueryFields = this.cfgQueryFieldDao.queryList(where);
        List<ServerQueryFieldDTO> resList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(cfgQueryFields)) {
            resList = cfgQueryFields.stream().map(cfgQueryField -> {
                ServerQueryFieldDTO queryField = new ServerQueryFieldDTO();
                queryField.setFieldId(cfgQueryField.getGuid());
                queryField.setMetaFieldId(cfgQueryField.getFieldaddonsguid());
                queryField.setMetaFieldCode(cfgQueryField.getMetaFieldCode());
                queryField.setFieldCode(cfgQueryField.getParametercode());
                queryField.setFieldName(cfgQueryField.getParametername());
                queryField.setFieldCondition(cfgQueryField.getParametercondition());
                queryField.setFieldSearchType(cfgQueryField.getParametertype());
                queryField.setFieldDefaultValue(cfgQueryField.getParametervalue());
                queryField.setFieldType(cfgQueryField.getParamformat());
                queryField.setRequiredFlag(cfgQueryField.getRequiredFlag());
                queryField.setRemark(cfgQueryField.getRemark());
                queryField.setFieldOrder(cfgQueryField.getQueryorder());
                queryField.setExt1(cfgQueryField.getExt1());
                // queryField.setDataOrder();
                return queryField;
            }).collect(Collectors.toList());

        }
        return resList;
    }


    private List<ServerShowFieldDTO> selectShowFieldList(String serverId) {
        CfgShowField where = new CfgShowField();
        where.setServiceid(serverId);
        List<CfgShowField> cfgShowFields = this.cfgShowFieldDao.queryList(where);
        List<ServerShowFieldDTO> resList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(cfgShowFields)) {
            resList = cfgShowFields.stream().map(cfgShowField -> {
                ServerShowFieldDTO res = new ServerShowFieldDTO();
                res.setFieldId(cfgShowField.getGuid());
                res.setMetaFieldId(cfgShowField.getFieldaddonsguid());
                res.setMetaFieldCode(cfgShowField.getFieldcode());
                res.setFieldCode(cfgShowField.getCustomalias());
                res.setFieldName(cfgShowField.getCustomfieldnamealias());
                res.setFieldType(cfgShowField.getFieldtype());
                res.setFieldOrder(cfgShowField.getShoworder());
                res.setRemark(cfgShowField.getRemark());
                return res;
            }).collect(Collectors.toList());
        }
        return resList;
    }

    private List<AcServiceFilterFields> selectFilterFieldList(String serverId) {
        AcServiceFilterFields where = new AcServiceFilterFields();
        where.setServiceId(serverId);
        return acServiceFilterFieldsDao.queryList(where);
    }


    private String getServerIdOrCode(ServerConfigDTO basicConfig) {
        String serverId = basicConfig.getServerId();
        if ((SINGLE_SERVER.equals(basicConfig.getServerType()) || SQL_SERVER.equals(basicConfig.getServerType()))
                && !serverId.equals(basicConfig.getServiceCode())
        ) {
            serverId = basicConfig.getServiceCode();
        }
        return serverId;
    }

}
